home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
programr
/
ole2book.zip
/
CHAP06.ZIP
/
CHAP06
/
DDATAOBJ
/
IDATAOBJ.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1993-04-21
|
12KB
|
477 lines
/*
* IDATAOBJ.CPP
* Data Object for Chapter 6
*
* Implementation of the IDataObject interface for CDataObject.
*
* Copyright (c)1993 Microsoft Corporation, All Rights Reserved
*
* Kraig Brockschmidt, Software Design Engineer
* Microsoft Systems Developer Relations
*
* Internet : kraigb@microsoft.com
* Compuserve: >INTERNET:kraigb@microsoft.com
*/
#include "dataobj.h"
/*
* CImpIDataObject::CImpIDataObject
* CImpIDataObject::~CImpIDataObject
*
* Parameters (Constructor):
* pObj LPVOID of the object we're in.
* punkOuter LPUNKNOWN to which we delegate.
*/
CImpIDataObject::CImpIDataObject(LPVOID pObj, LPUNKNOWN punkOuter)
{
m_cRef=0;
m_pObj=pObj;
m_punkOuter=punkOuter;
return;
}
CImpIDataObject::~CImpIDataObject(void)
{
return;
}
/*
* CImpIDataObject::QueryInterface
* CImpIDataObject::AddRef
* CImpIDataObject::Release
*
* Purpose:
* IUnknown members for CImpIDataObject object.
*/
STDMETHODIMP CImpIDataObject::QueryInterface(REFIID riid, LPVOID FAR *ppv)
{
return m_punkOuter->QueryInterface(riid, ppv);
}
STDMETHODIMP_(ULONG) CImpIDataObject::AddRef(void)
{
++m_cRef;
return m_punkOuter->AddRef();
}
STDMETHODIMP_(ULONG) CImpIDataObject::Release(void)
{
--m_cRef;
return m_punkOuter->Release();
}
/*
* CImpIDataObject::GetData
*
* Purpose:
* Retrieves data described by a specific FormatEtc into a StgMedium
* allocated by this function. Used like GetClipboardData.
*
* Parameters:
* pFE LPFORMATETC describing the desired data.
* pSTM LPSTGMEDIUM in which to return the data.
*
* Return Value:
* HRESULT NOERROR on success, error code otherwise.
*/
STDMETHODIMP CImpIDataObject::GetData(LPFORMATETC pFE, LPSTGMEDIUM pSTM)
{
LPCDataObject pObj=(LPCDataObject)m_pObj;
UINT cf=pFE->cfFormat;
/*
* This function is just cycling through each format you support
* and finding a match with the requested one, rendering that
* data, then returning NOERROR, otherwise returning either
* DATA_E_FORMATETC or STG_E_MEDIUMFULL on error.
*/
//Check the aspects we support.
if (!(DVASPECT_CONTENT & pFE->dwAspect))
return ResultFromScode(DATA_E_FORMATETC);
switch (cf)
{
case CF_METAFILEPICT:
if (!(TYMED_MFPICT & pFE->tymed))
break;
return pObj->RenderMetafilePict(pSTM);
case CF_BITMAP:
if (!(TYMED_GDI & pFE->tymed))
break;
return pObj->RenderBitmap(pSTM);
case CF_TEXT:
if (!(TYMED_HGLOBAL & pFE->tymed))
break;
return pObj->RenderText(pSTM);
default:
break;
}
return ResultFromScode(DATA_E_FORMATETC);
}
/*
* CImpIDataObject::GetDataHere
*
* Purpose:
* Renders the specific FormatEtc into caller-allocated medium
* provided in pSTM.
*
* Parameters:
* pFE LPFORMATETC describing the desired data.
* pSTM LPSTGMEDIUM providing the medium into which
* wer render the data.
*
* Return Value:
* HRESULT NOERROR on success, error code otherwise.
*/
STDMETHODIMP CImpIDataObject::GetDataHere(LPFORMATETC pFE, LPSTGMEDIUM pSTM)
{
//We don't implement this now.
return ResultFromScode(E_NOTIMPL);
}
/*
* CImpIDataObject::QueryGetData
*
* Purpose:
* Tests if a call to ::GetData with this FormatEtc will provide
* any rendering; used like IsClipboardFormatAvailable.
*
* Parameters:
* pFE LPFORMATETC describing the desired data.
*
* Return Value:
* HRESULT NOERROR on success, error code otherwise.
*/
STDMETHODIMP CImpIDataObject::QueryGetData(LPFORMATETC pFE)
{
LPCDataObject pObj=(LPCDataObject)m_pObj;
UINT cf=pFE->cfFormat;
BOOL fRet=FALSE;
/*
* This function is just cycling through each format you support
* and finding a match with the requested one, returning NOERROR
* if you do have it, S_FALSE if you don't.
*/
//Check the aspects we support.
if (!(DVASPECT_CONTENT & pFE->dwAspect))
return ResultFromScode(DATA_E_FORMATETC);
switch (cf)
{
case CF_METAFILEPICT:
fRet=(BOOL)(pFE->tymed & TYMED_MFPICT);
break;
case CF_BITMAP:
fRet=(BOOL)(pFE->tymed & TYMED_GDI);
break;
case CF_TEXT:
fRet=(BOOL)(pFE->tymed & TYMED_HGLOBAL);
break;
default:
fRet=FALSE;
break;
}
return fRet ? NOERROR : ResultFromScode(S_FALSE);
}
/*
* CImpIDataObject::GetCanonicalFormatEtc
*
* Purpose:
* Provides the caller with an equivalent FormatEtc to the one
* provided when different FormatEtcs will produce exactly the
* same renderings.
*
* Parameters:
* pFEIn LPFORMATETC of the first description.
* pFEOut LPFORMATETC of the equal description.
*
* Return Value:
* HRESULT NOERROR on success, error code otherwise.
*/
STDMETHODIMP CImpIDataObject::GetCanonicalFormatEtc(LPFORMATETC pFEIn
, LPFORMATETC pFEOut)
{
/*
* 1. If you support an equivalent of pFEIn, return it in pFEOut.
* 2. Return NOERROR if you filled pFEOut with anything, otherwise
* return DATA_S_SAMEFORMATETC. If you say that all renderings
* are identical, return DATA_S_SAMEFORMATETC.
*/
return ResultFromScode(DATA_S_SAMEFORMATETC);
}
/*
* CImpIDataObject::SetData
*
* Purpose:
* Places data described by a FormatEtc and living in a StgMedium
* into the object. The object may be responsible to clean up the
* StgMedium before exiting.
*
* Parameters:
* pFE LPFORMATETC describing the data to set.
* pSTM LPSTGMEDIUM containing the data.
* fRelease BOOL indicating if this function is responsible for
* freeing the data.
*
* Return Value:
* HRESULT NOERROR on success, error code otherwise.
*/
STDMETHODIMP CImpIDataObject::SetData(LPFORMATETC pFE, STGMEDIUM FAR *pSTM
, BOOL fRelease)
{
//We don't handle SetDatas here.
return ResultFromScode(DATA_E_FORMATETC);
}
/*
* CImpIDataObject::EnumFormatEtc
*
* Purpose:
* Returns an IEnumFORMATETC object through which the caller can iterate
* to learn about all the data formats this object can provide through
* either ::GetData[Here] or ::SetData.
*
* Parameters:
* dwDir DWORD describing a data direction, either DATADIR_SET
* or DATADIR_GET.
* ppEnum LPENUMFORMATETC FAR * in which to return the pointer
* to the enumerator.
*
* Return Value:
* HRESULT NOERROR on success, error code otherwise.
*/
STDMETHODIMP CImpIDataObject::EnumFormatEtc(DWORD dwDir
, LPENUMFORMATETC FAR *ppEnum)
{
LPCDataObject pObj=(LPCDataObject)m_pObj;
/*
* We only support ::GetData in this object so we return NULL for
* DATADIR_SET. Otherwise we instantiate one of our CEnumFormatEtc
* objects which has all the appropriate functions; we only need to
* tell it where our arrays live.
*
* The m_punkOuter passed to the enumerator allows the enumerator
* to AddRef and Release our controlling unknown as it receives
* reference counting calls. By calling AddRef itself, it can
* insure that the object that holds the data context will stick
* around as long as the enumerator itself is around. Otherwise
* it could be enumerating through bogus data.
*/
switch (dwDir)
{
case DATADIR_GET:
*ppEnum=(LPENUMFORMATETC)new CEnumFormatEtc(m_punkOuter
, pObj->m_cfeGet, pObj->m_rgfeGet);
break;
case DATADIR_SET:
*ppEnum=NULL;
break;
default:
*ppEnum=NULL;
break;
}
if (NULL==*ppEnum)
return ResultFromScode(E_FAIL);
else
(*ppEnum)->AddRef();
return NOERROR;
}
/*
* CImpIDataObject::DAdvise
*
* Purpose:
* Provides the data object with an IAdviseSink object that we are
* responsible to notify when the data changes.
*
* Parameters:
* ppFE LPFORMATETC
* dwFlags DWORD carrying flags indicating how the advise sink
* wants to be treated.
* pIAdviseSink LPADVISESINK to the object to notify on data changes.
* pdwConn LPDWORD into which we store a DWORD key identifying
* the advise connection.
*
* Return Value:
* HRESULT NOERROR on success, error code otherwise.
*/
STDMETHODIMP CImpIDataObject::DAdvise(LPFORMATETC pFE, DWORD dwFlags
, LPADVISESINK pIAdviseSink, LPDWORD pdwConn)
{
LPCDataObject pObj=(LPCDataObject)m_pObj;
HRESULT hr;
/*
* 1. If you've already created an advise holder for this object,
* skip to step 3. If there are multiple clients connected the
* one advise holder takes care of it when we call it's Advise.
* 2. Create and save an advise holder interface using
* CreateDataAdviseHolder. Return E_OUTOFMEMORY on failure.
* 3. Call the IDataAdviseHolder::Advise member passing to it the
* advise sink and pdwConn.
* 4. Return the HRESULT from step 3;
*/
if (NULL==pObj->m_pIDataAdviseHolder)
{
hr=CreateDataAdviseHolder(&pObj->m_pIDataAdviseHolder);
if (FAILED(hr))
return ResultFromScode(E_OUTOFMEMORY);
}
hr=pObj->m_pIDataAdviseHolder->Advise((LPDATAOBJECT)this, pFE
, dwFlags, pIAdviseSink, pdwConn);
return hr;
}
/*
* CImpIDataObject::DUnadvise
*
* Purpose:
* Turns off advising previously set up with ::Advise.
*
* Parameters:
* dwConn DWORD connection key returned from ::Advise.
*
* Return Value:
* HRESULT NOERROR on success, error code otherwise.
*/
STDMETHODIMP CImpIDataObject::DUnadvise(DWORD dwConn)
{
LPCDataObject pObj=(LPCDataObject)m_pObj;
HRESULT hr;
/*
* 1. If you have stored and advise holder from IDataObject::Advise
* then pass dwConn to it's Unadvise and return the HRESULT from
* that function.
* 2. If you have no advise holder, return E_FAIL;
*/
if (NULL==pObj->m_pIDataAdviseHolder)
return ResultFromScode(E_FAIL);
hr=pObj->m_pIDataAdviseHolder->Unadvise(dwConn);
return hr;
}
/*
* CImpIDataObject::EnumDAdvise
*
* Purpose:
* Returns an enumerator object through which the caller can find all
* the agents currently receiving advises on this data object.
*
* Parameters:
* ppEnum LPENUMSTATDATA FAR * in which to return the enumerator.
*
* Return Value:
* HRESULT NOERROR on success, error code otherwise.
*/
STDMETHODIMP CImpIDataObject::EnumDAdvise(LPENUMSTATDATA FAR *ppEnum)
{
LPCDataObject pObj=(LPCDataObject)m_pObj;
HRESULT hr;
/*
* 1. If you have a stored IDataAdviseHolder, pass this request on
* to its EnumAdvise and return the HRESULT from that function.
* 2. Otherwise return E_FAIL.
*/
if (NULL==pObj->m_pIDataAdviseHolder)
return ResultFromScode(E_FAIL);
hr=pObj->m_pIDataAdviseHolder->EnumAdvise(ppEnum);
return hr;
}